package org.demo.test.socket.client;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

public class SocketClient {

	/*
	 * CountDownLatch闭锁，在执行await时使得当前现场处于等待状态，直到CountDownLatch对象countDown至0时，
	 * 对应的等待门开启，所有在该对象await处的现场可同时往下执行
	 */
	public static CountDownLatch cdl2 = new CountDownLatch(2);
	
	public static void main(String[] args) {
		int clientNum = 1;
		try {
			CountDownLatch cdl = new CountDownLatch(clientNum);
			Thread tt = null;
			for(int index = 0; index < clientNum; index++, cdl.countDown()){
				Thread.sleep(2000);
				Thread t = new Thread(new RequestThread(cdl,index));
				if(index == 0){
					tt = t;
				}
				t.start();
			}
			
			Thread.sleep(5000);
			synchronized (SocketClient.class) {
				SocketClient.cdl2.countDown();
				System.out.println("主线程进入等待!");
				System.out.println("线程0状态："+tt.getState().toString());
				SocketClient.class.wait();
			}
			System.out.println("主线程解除等待!");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}


class RequestThread implements Runnable{
	
	private CountDownLatch cdl;
	
	private int threadid;
	
	public RequestThread(CountDownLatch cdl,int threadid) {
		this.cdl = cdl;
		this.threadid = threadid;
	}

	@Override
	public void run() {
		Socket socket = null;
		OutputStream os = null;
		InputStream is = null;
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
		try {
			socket = new Socket("127.0.0.1",6666);
			os = socket.getOutputStream();
			is = socket.getInputStream();
			System.out.println(df.format(new Date())+" 线程="+this.threadid+" 连接就绪，等待其他线程！");
			this.cdl.await();
			System.out.println(df.format(new Date())+" 线程="+this.threadid+" 准备发送请求1");
			os.write(("线程="+this.threadid+" 发送请求!").getBytes());
			os.flush();
			System.out.println(df.format(new Date())+" 线程="+this.threadid+" 结束发送请求1");
			
			Thread.sleep(5000);
			System.out.println(df.format(new Date())+" 线程="+this.threadid+" 准备发送请求2");
			os.write(("线程="+this.threadid+" 再次发送请求#").getBytes());
			os.flush();
			System.out.println(df.format(new Date())+" 线程="+this.threadid+" 结束发送请求2");
			int maxLen = 1024;
			byte[] context = new byte[maxLen];
			String message = "";
			System.out.println(df.format(new Date())+" 准备接受反馈信息");
			while(is.read(context, 0, maxLen) != -1){
				message += new String(context);
			}
			System.out.println("接受反馈信息结束");
			System.out.println(message);
			if(this.threadid == 0){
				synchronized (SocketClient.class) {
					SocketClient.cdl2.countDown();
					System.out.println(df.format(new Date())+" 线程="+this.threadid+"进入等待!");
					SocketClient.class.wait();
					System.out.println(df.format(new Date())+" 线程="+this.threadid+"解除等待!");
				}
			}
			
			if(this.threadid == 1){
				System.out.println(df.format(new Date())+" 线程="+this.threadid+"等待唤醒其他线程!");
				SocketClient.cdl2.await();
				System.out.println(df.format(new Date())+" 线程="+this.threadid+"开始唤醒其他线程!");
				Thread.sleep(2000);
				synchronized (SocketClient.class) {
					System.out.println(df.format(new Date())+" 线程="+this.threadid+"唤醒其他线程!");
					/*
					 *notify随机唤醒一个在锁定对象上的等待线程
					 * notifyAll唤醒所有锁定对象上的等待线程
					 */
					// SocketClient.class.notifyAll();
					// SocketClient.class.notify();
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			try{
				is.close();
				os.close();
				socket.close();
			}catch(IOException e){e.printStackTrace();}
		}
	}
}